#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#include "game_server.h"
#include "game_log.h"
#include "daemonize.h"
#include "do_sql.h"

using namespace std;

bool parse_arg(int argc, char **argv)
{
	int flag = 0;
	int oc;   /* option chacb. */
	char ic;  /* invalid chacb. */

	YXJMJ_SERVER._is_daemonize = 0;
	while ((oc = getopt(argc, argv, "Df:p:")) != -1) {
		switch (oc) {
		case 'D':
			YXJMJ_SERVER._is_daemonize = 1;
			break;
		case 'f':
			flag++;
			YXJMJ_SERVER._conf_file = string(optarg);
			break;
		case 'p':
			flag++;
			YXJMJ_SERVER._server_id = atoi(optarg);
			break;
		case '?':
			ic = (char)optopt;
			printf("invalid \'%c\'\n", ic);
			break;
		case ':':
			printf("lack option arg\n");
			break;
		}
	}
	if (flag != 2)
		return false;

	return true;
}

static int set_rlimit(int resource, int n = 0)
{
	struct rlimit rt;
	rt.rlim_max = rt.rlim_cur = (n == 0) ? RLIM_INFINITY : n;
	if (setrlimit(resource, &rt) == -1) {
		GAME_LOG.error("File: %s Func: %s Line: %d => setrlimit %s.\n",
			__FILE__, __FUNCTION__, __LINE__, strerror(errno));
		return -1;
	}

	return 0;
}

int main(int argc, char **argv)
{
	//读取参数
	if (!parse_arg(argc, argv))
	{
		GAME_LOG.fatal("File: %s Func: %s Line: %d => parse_arg.\n",
			__FILE__, __FUNCTION__, __LINE__);
		exit(1);
	}

	//初始化配置文件
	if (!YXJMJ_SERVER._config.InitConfig(YXJMJ_SERVER._conf_file)) {
		GAME_LOG.fatal("File: %s Func: %s Line: %d => init_conf.\n",
			__FILE__, __FUNCTION__, __LINE__);
		exit(1);
	}
	//是否进入后台运行
	if (YXJMJ_SERVER._is_daemonize == 1)
		daemonize();
	signal(SIGPIPE, SIG_IGN);

	//将进程号写入pid文件
	int ret = single_instance_running(std::string("proc/" + std::to_string(YXJMJ_SERVER._server_id) + "/yxjmj.pid").c_str());
	if (ret < 0)
	{
		GAME_LOG.fatal("File: %s Func: %s Line: %d => single_instance_running.\n",
			__FILE__, __FUNCTION__, __LINE__);
		exit(1);
	}
	set_rlimit(RLIMIT_NOFILE, 102400);

	if (YXJMJ_SERVER._game_flag < 1000000)
	{
		YXJMJ_SERVER._rooms.ChangeRoomCardType();
	}
	//初始化游戏内容
	if (!YXJMJ_SERVER.InitGameConfig())
	{
		GAME_LOG.fatal("File: %s Func: %s Line: %d => init_game_config.\n",
			__FILE__, __FUNCTION__, __LINE__);
		exit(1);
	}

	struct event_base *base;
	struct evconnlistener *listener;
	struct event *signal_event;
#ifdef _WIN32
	WSADATA wsa_data;
	WSAStartup(0x0201, &wsa_data);
#endif

	base = event_base_new();
	if (!base) {
		fprintf(stderr, "Could not initialize libevent!\n");
		return 1;
	}

	TcpNetwork net(base);
	if (net.InitListen(YXJMJ_SERVER._port))
	{
		GAME_LOG.fatal("File: %s Func: %s Line: %d => InitListen.\n",
			__FILE__, __FUNCTION__, __LINE__);
		exit(1);
	}
	YXJMJ_SERVER._tcp_network = &net;
	
	event_base_dispatch(base);

	evconnlistener_free(listener);
	event_free(signal_event);
	event_base_free(base);

	printf("done\n");
	return 0;
}